package br.usp.ime.ingpos.services;

import java.util.Date;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.springframework.web.jsf.FacesContextUtils;

import br.com.caelum.vraptor.core.Localization;
import br.com.caelum.vraptor.ioc.Component;
import br.com.caelum.vraptor.ioc.RequestScoped;
import br.usp.ime.ingpos.modelo.Candidato;
import br.usp.ime.ingpos.modelo.Curriculo;
import br.usp.ime.ingpos.modelo.DadosPessoais;
import br.usp.ime.ingpos.modelo.Email;
import br.usp.ime.ingpos.modelo.Endereco;
import br.usp.ime.ingpos.modelo.Perfil;
import br.usp.ime.ingpos.modelo.RegistroNovoUsuario;
import br.usp.ime.ingpos.modelo.TipoPerfil;
import br.usp.ime.ingpos.modelo.Usuario;
import br.usp.ime.ingpos.modelo.dao.CandidatoDAO;
import br.usp.ime.ingpos.modelo.dao.PerfilDao;
import br.usp.ime.ingpos.modelo.dao.RegistroNovoUsuarioDao;

@RequestScoped
@Component
public class RegistroNovoUsuarioService
{
    public static enum RegistroResultado
    {
        SUCESSO,
        NOME_OU_EMAIL_JA_EXISTENTE,
        CHAVE_ATIVACAO_NAO_EXISTE,
        USUARIO_JA_ATIVADO,
        ERRO_ENVIAR_EMAIL
    }

    private final RegistroNovoUsuarioDao registroNovoUsuarioDAO;
    private final UsuarioService usuarioService;
    private final CandidatoDAO candidatoDao;
    private final PerfilDao perfilDao;
    private final EmailService emailService;
    private final HttpServletRequest httpServletRequest;
    private final Localization localization;

    public RegistroNovoUsuarioService(
        final RegistroNovoUsuarioDao registroNovoUsuarioDAO,
        final PerfilDao perfilDao,
        final CandidatoDAO candidatoDao,
        final UsuarioService usuarioService,        
        final EmailService emailService,
        final Localization localization,
        final HttpServletRequest httpServletRequest )
    {
        this.registroNovoUsuarioDAO = registroNovoUsuarioDAO;
        this.perfilDao = perfilDao;
        this.candidatoDao = candidatoDao;
        this.usuarioService = usuarioService;        
        this.emailService = emailService;
        this.localization = localization;
        this.httpServletRequest = httpServletRequest;

    }
    
    private String getUrl(){
        final String url;
        if( httpServletRequest == null ) {
            // TODO: Verificar como remover esta url para efeito de testes
            url = "http://localhost:8080/Ingresso-na-Pos";
        } else {
            url = httpServletRequest.getRequestURL().substring(0 , httpServletRequest.getRequestURL().length()-9);
        }

        return url;
    }

    private String getUrlRegistro()
    {
        final String urlRegistro;
        if( httpServletRequest == null ) {
            // TODO: Verificar como remover esta url para efeito de testes
            urlRegistro = "http://localhost:8080/Ingresso-na-Pos/registro";
        } else {
            urlRegistro = httpServletRequest.getRequestURL().toString();
        }

        return urlRegistro;
    }

    public RegistroResultado registrar(
        final RegistroNovoUsuario registroNovoUsuario )
    {
        RegistroResultado resultado;

        final Usuario usuarioExistente = usuarioService.procurarPorEmail( registroNovoUsuario.getEmail() );
        final RegistroNovoUsuario registroNovoUsuarioExistente = registroNovoUsuarioDAO.procurarPorEmail( registroNovoUsuario.getEmail() );

        if( registroNovoUsuarioExistente != null || usuarioExistente != null) {
            resultado = RegistroResultado.NOME_OU_EMAIL_JA_EXISTENTE;
        } else {

            try {
                registroNovoUsuario.setDataHoraRegistro( new Date() );
                registroNovoUsuario.definirChaveAtivacao();

                emailService.enviarEmail( construirEmailRegistro( registroNovoUsuario ) );

                registroNovoUsuarioDAO.save( registroNovoUsuario );

                resultado = RegistroResultado.SUCESSO;

            } catch( EmailException e ) {
                resultado = RegistroResultado.ERRO_ENVIAR_EMAIL;
            }
        }

        return resultado;
    }

    private Email construirEmailRegistro(
        final RegistroNovoUsuario registroNovoUsuario )
    {
        final StringBuilder linkBuilder = new StringBuilder();
        linkBuilder.append( getUrlRegistro() );
        linkBuilder.append( "/ativacao/" );
        linkBuilder.append( registroNovoUsuario.getChaveAtivacao() );

        final String assunto = localization.getMessage( "registro_email_assunto" );
        final String conteudo = localization.getMessage( "registro_email_conteudo", registroNovoUsuario.getNomeCompleto(), getUrl(), linkBuilder.toString());

        return emailService.construirEmail( assunto, conteudo+localization.getMessage( "email_rodape"), registroNovoUsuario.getEmail() );
    }

    public RegistroResultado ativar(
        String chaveAtivacao )
    {

        final RegistroResultado resultado;
        final RegistroNovoUsuario registroNovoUsuario = registroNovoUsuarioDAO.procurarPorChaveAtivacao( chaveAtivacao );

        if( registroNovoUsuario == null ) {
            resultado = RegistroResultado.CHAVE_ATIVACAO_NAO_EXISTE;
        } else {
        	Perfil perfil = perfilDao.findById(TipoPerfil.CANDIDATO.getId());

            Usuario novoUsuario = usuarioService.procurarPorEmail( registroNovoUsuario.getEmail() );

            if( novoUsuario != null ) {
                resultado = RegistroResultado.USUARIO_JA_ATIVADO;
            } else {
                Candidato novoCandidato = new Candidato();
                novoCandidato.setEmail( registroNovoUsuario.getEmail() );
                novoCandidato.setSenha( registroNovoUsuario.getSenha() );
                novoCandidato.setPerfil( perfil );

                final DadosPessoais dadosPessoais = novoCandidato.getDadosPessoais();
                dadosPessoais.setNomeCompleto( registroNovoUsuario.getNomeCompleto() );

                usuarioService.salvar( novoCandidato );
                candidatoDao.save(novoCandidato);
                
                registroNovoUsuarioDAO.delete(registroNovoUsuario);

                resultado = RegistroResultado.SUCESSO;
            }
        }
        return resultado;
    }

}
